home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / st80_pr4.lha / st80_pre4 / Foible / SDS / SDS.st < prev    next >
Text File  |  1993-07-24  |  42KB  |  1,635 lines

  1. CanvasController subclass: #SDSController
  2.     instanceVariableNames: ''
  3.     classVariableNames: 'YellowButtonMenu YellowButtonMenuForBox YellowButtonMenuForLink YellowButtonMessages YellowButtonMessagesForBox YellowButtonMessagesForLink '
  4.     poolDictionaries: ''
  5.     category: 'SDS'!
  6.  
  7.  
  8. !SDSController methodsFor: 'menu messages'!
  9.  
  10. yellowButtonActivity
  11.     "my context sensitive yellowButtonActivity (different 
  12.     yellowButtonMenu depends on where the mouse clicked (on box, link 
  13.     or canvas)"
  14.  
  15.     | index aPoint aFoible |
  16.     aPoint _ Sensor cursorPoint.
  17.     aPoint _ (view inverseDisplayTransform: aPoint) rounded.
  18.     aFoible _ model find: aPoint.
  19.     aFoible ~= nil
  20.         ifTrue: [(aFoible isKindOf: SDSBox)
  21.                 ifTrue: 
  22.                     [index _ YellowButtonMenuForBox startUpYellowButton.
  23.                     index ~= 0
  24.                         ifTrue: 
  25.                             [lastYellowButtonMessage _ YellowButtonMessagesForBox at: index.
  26.                             self menuMessageReceiver perform: lastYellowButtonMessage with: aFoible]]
  27.                 ifFalse: 
  28.                     [index _ YellowButtonMenuForLink startUpYellowButton.
  29.                     index ~= 0
  30.                         ifTrue: 
  31.                             [lastYellowButtonMessage _ YellowButtonMessagesForLink at: index.
  32.                             self menuMessageReceiver perform: lastYellowButtonMessage with: aFoible]]]
  33.         ifFalse: 
  34.             [index _ YellowButtonMenu startUpYellowButton.
  35.             index ~= 0
  36.                 ifTrue: 
  37.                     [lastYellowButtonMessage _ YellowButtonMessages at: index.
  38.                     self model perform: lastYellowButtonMessage]]! !
  39.  
  40. !SDSController methodsFor: 'basic control sequence'!
  41.  
  42. controlInitialize
  43.     "Save old cursor, install new one"
  44.  
  45.     model update.
  46.     lastYellowButtonMessage _ nil.
  47.     lastYellowButtonMessage = #createIcon "redraw display to show new icon"
  48.         ifTrue: 
  49.             [lastYellowButtonMessage _ nil.
  50.             view display].
  51.     saveCursor _ Cursor currentCursor.
  52.     model cursor show.
  53.     tool controlInitialize! !
  54. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  55.  
  56. SDSController class
  57.     instanceVariableNames: ''!
  58.  
  59.  
  60. !SDSController class methodsFor: 'class initialization'!
  61.  
  62. initialize
  63.     "initialize class variables for menus."
  64.  
  65.     "my menu when yellow button clicked on a box"
  66.     YellowButtonMenuForBox _ PopUpMenu labels: 'move\delete\rename\edit equation\add to graph\delete from graph\show table' withCRs lines: #(3 4 6).
  67.     YellowButtonMessagesForBox _ #(#moveBox: #deleteBox: #renameBox:  #editEquation: #addToGraph: #deleteFromGraph: #showTable:).
  68.  
  69.     "my menu when yellow button clicked over a link"
  70.     YellowButtonMenuForLink _ PopUpMenu labels: 'delete'.
  71.     YellowButtonMessagesForLink _ #(#deleteLink:).
  72.  
  73.     "my menu when yellow button clicked on canvas"
  74.     YellowButtonMenu _ PopUpMenu labels: 'time parameter\run simulation\list equations\calculation mode\show graph\graph parameters' withCRs lines: #(2 4 ).
  75.     YellowButtonMessages _ #(#timeDefinition #runSimulation #listEquations #setCalculationMode #showGraph #graphParameters)! !
  76.  
  77. SDSController initialize!
  78.  
  79.  
  80. FoibleProgram subclass: #SDSProgram
  81.     instanceVariableNames: ''
  82.     classVariableNames: ''
  83.     poolDictionaries: ''
  84.     category: 'SDS'!
  85. SDSProgram comment:
  86. 'I am the top-level model of any SDS environment. Now I am defined only to 
  87. overide the ''initialize:'' message. '!
  88.  
  89.  
  90. !SDSProgram methodsFor: 'initialize'!
  91.  
  92. initialize: anSDSManager
  93.     "Initialize the 'managers' instance variable of this new instance to
  94.     be a SDSManager"
  95.  
  96.     managers  _ OrderedCollection with: anSDSManager.
  97.     anSDSManager program: self.
  98.     self name: 'System Dynamic Simulator'!
  99.  
  100. nitialize: anSDSManager
  101.     "Initialize the 'managers' instance variable of this new instance to
  102.     be a SDSManager"
  103.  
  104.     managers  _ OrderedCollection with: anSDSManager.
  105.     anSDSManager program: self.
  106.     self name: 'System Dynamic Simulator'! !
  107.  
  108. FoibleLink subclass: #SDSLink
  109.     instanceVariableNames: ''
  110.     classVariableNames: ''
  111.     poolDictionaries: ''
  112.     category: 'SDS'!
  113. SDSLink comment:
  114. 'See comments in FoibleLink (my superclass).'!
  115.  
  116.  
  117. !SDSLink methodsFor: 'interface tests'!
  118.  
  119. acceptsArcs: aPoint 
  120.     "Return whether I give Arcs at the user interface"
  121.  
  122.     ^false!
  123.  
  124. acceptsDataLinks: aPoint 
  125.     "Return whether I accept DataLinks at the user interface"
  126.  
  127.     ^false!
  128.  
  129. acceptsPipes: aPoint 
  130.     "Return whether I accept Pipes at the user interface"
  131.  
  132.     ^false!
  133.  
  134. givesArcs: aPoint 
  135.     "Return whether I give Arcs at the user interface"
  136.  
  137.     ^false!
  138.  
  139. givesDataLinks: aPoint
  140.     "Return whether I give DataLinks at the user interface"
  141.  
  142.     ^false!
  143.  
  144. givesPipes: aPoint 
  145.     "Return whether I give Pipes at the user interface"
  146.  
  147.     ^false! !
  148.  
  149. !SDSLink methodsFor: 'private'!
  150.  
  151. addLinesFor: aBox movedBy: aPoint 
  152.     "replace single line in path between boxes with three lines 
  153.     note: this should be called only if I have 1 line in the path"
  154.     "Modification made to overide my superclass method to make the line 
  155.     doesn't overlap with the box"
  156.  
  157.     | newPath theLine oldBegin oldEnd newBegin newEnd loc2 loc3 aRect sourceBox toBox |
  158.     newPath _ OrderedCollection new.
  159.     theLine _ self forms last.
  160.     aRect _ theLine relativeRectangle.
  161.     oldBegin _ theLine beginPoint.
  162.     oldEnd _ theLine endPoint.
  163.     sourceBox := self source box.
  164.     toBox := self toBox.
  165.     sourceBox = aBox
  166.         ifTrue: 
  167.             ["for firstLine horizontal"
  168.             newBegin _ oldBegin + aPoint.
  169.             newEnd _ oldEnd]
  170.         ifFalse: 
  171.             [newEnd _ oldEnd + aPoint.
  172.             newBegin _ oldBegin].
  173.     theLine horizontal
  174.         ifTrue: 
  175.             [loc2 _ (newBegin x + newEnd x) abs // 2 @ newBegin y.
  176.             loc3 _ (newBegin x + newEnd x) abs // 2 @ newEnd y.
  177.             newBegin x > loc2 x
  178.                 ifTrue: [newBegin x: sourceBox boundingBox origin x]
  179.                 ifFalse: [newBegin x: sourceBox boundingBox corner x].
  180.             newEnd x > loc3 x
  181.                 ifTrue: [newEnd x: toBox boundingBox origin x]
  182.                 ifFalse: [newEnd x: toBox boundingBox corner x]]
  183.         ifFalse: 
  184.             [loc2 _ newBegin x @ ((newBegin y + newEnd y) abs // 2).
  185.             loc3 _ newEnd x @ ((newBegin y + newEnd y) abs // 2).
  186.             newBegin y > loc2 y
  187.                 ifTrue: [newBegin y: sourceBox boundingBox origin y]
  188.                 ifFalse: [newBegin y: sourceBox boundingBox corner y].
  189.             newEnd y > loc3 y
  190.                 ifTrue: [newEnd y: toBox boundingBox origin y]
  191.                 ifFalse: [newEnd y: toBox boundingBox corner y]].
  192.     newPath add: (self defaultLineClass from: newBegin to: loc2); add: (self defaultLineClass from: loc2 to: loc3); add: (self defaultLineClass from: loc3 to: newEnd).
  193.     self
  194.         replacePathFromLine: theLine
  195.         toLine: theLine
  196.         withLines: newPath.
  197.     newPath do: [:each | aRect _ aRect merge: each relativeRectangle].
  198.     ^aRect!
  199.  
  200. stretchLinesFor: aBox movedBy: aPoint
  201.     "adjust first 2 (or last 2) lines in path due to aBox moving"
  202.     "redefined to make the line doesn't overlap the box"
  203.  
  204.     | line1 line2 loc1 loc2 loc3 newLines aRect |
  205.     newLines_OrderedCollection new.
  206.     (self source box = aBox)  "link is coming out of box"
  207.         ifTrue:[line1_self forms first.
  208.                 line2_line1 next.
  209.                 loc1_line1 beginPoint+aPoint.
  210.                 loc3_line2 endPoint.
  211.                 line1 horizontal
  212.                     ifTrue: [(loc1 x < loc3 x)
  213.                             ifTrue: [loc1  x: 
  214.                                     aBox boundingBox corner x]
  215.                             ifFalse:[loc1 x: 
  216.                                     aBox boundingBox origin x]
  217.                             ]
  218.                     ifFalse: [(loc1 y < loc3 y)
  219.                             ifTrue: [loc1 y: 
  220.                                     aBox boundingBox corner y]
  221.                             ifFalse:[loc1 y: 
  222.                                     aBox boundingBox origin y]
  223.                             ]
  224.                 ]                    
  225.         ifFalse:[line2_self forms last.  "link is going into box"
  226.                 line1_line2 prev.
  227.                 loc3_line2 endPoint+aPoint.
  228.                 loc1_line1 beginPoint.
  229.                 line2 horizontal
  230.                     ifTrue: [(loc3 x < loc1 x)
  231.                             ifTrue: [loc3 x: 
  232.                                     aBox boundingBox corner x]
  233.                             ifFalse:[loc3 x: 
  234.                                     aBox boundingBox origin x]
  235.                             ]
  236.                     ifFalse: [(loc3 y < loc1 y)
  237.                             ifTrue: [loc3 y: 
  238.                                     aBox boundingBox corner y]
  239.                             ifFalse:[loc3 y: 
  240.                                     aBox boundingBox origin y]
  241.                             ]
  242.                 ].
  243.     line1 horizontal
  244.         ifTrue:[loc2_loc3 x@loc1 y]
  245.         ifFalse:[loc2_loc1 x@loc3 y].
  246.     " lines may change direction, so just replace them "
  247.     newLines     add: (self defaultLineClass from: loc1 to: loc2);
  248.                 add: (self defaultLineClass from: loc2 to: loc3).
  249.     self replacePathFromLine: line1 toLine: line2 withLines: newLines.
  250.     aRect _ line1 relativeRectangle merge: line2 relativeRectangle.
  251.     newLines do: [:each | aRect _ aRect merge: each relativeRectangle].
  252.     ^ aRect! !
  253.  
  254. !SDSLink methodsFor: 'removing'!
  255.  
  256. delete
  257.     "delete myself"
  258.         
  259.     | aRect |
  260.     aRect _ self remove.
  261.     self owner changed: aRect.! !
  262.  
  263. !SDSLink methodsFor: 'initialization'!
  264.  
  265. from: aSource to: aDest withPath: newPath 
  266.     "Initialize this FoibleLink linked from aSource to 
  267.     aDest, using the given newPath to make my form"
  268.     "there is a slight modification made here, i.e. I'll have both source and 
  269.     destination box before 'addlink:' message is send"
  270.  
  271.     source isNil ifFalse: [self error: 'cannot re-initialize a ' , self class name].
  272.     (aDest box linkedTo: aSource box)
  273.         ifTrue: 
  274.             [PopUpNotifier message: 'Circular link: ' , aSource name , '  is already connected to ' , aDest name.
  275.             ^nil].    "this modification is made to make link already has both source and 
  276.     destination before a addlink: message is sent to a box"
  277.     source _ aSource.
  278.     destination _ aDest.
  279.     source addLink: self.
  280.     destination addLink: self.
  281.     self path: newPath! !
  282. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  283.  
  284. SDSLink class
  285.     instanceVariableNames: ''!
  286.  
  287.  
  288. !SDSLink class methodsFor: 'form access'!
  289.  
  290. iconDirectory
  291.     "return the directory that contains the icons for the Stella"
  292.  
  293.     ^SDSDirectory iconDirectory! !
  294.  
  295. SDSLink subclass: #ArcLink
  296.     instanceVariableNames: ''
  297.     classVariableNames: ''
  298.     poolDictionaries: ''
  299.     category: 'SDS'!
  300. ArcLink comment:
  301. 'I am a link to pass value.'!
  302.  
  303.  
  304. !ArcLink methodsFor: 'initialization'!
  305.  
  306. from: aSource to: aDest withPath: newPath 
  307.     "Initialize this ArcLink linked from aSource to aDest, using the given 
  308.     newPath to make my form"
  309.  
  310.     source isNil ifFalse: [self error: 'cannot re-initialize a ' , self class name].
  311.     aDest box acceptsArcs ifFalse: [^nil].
  312.     (aDest box arcedTo: aSource box)
  313.         ifTrue: 
  314.             [PopUpNotifier message: 'Circular link: ' , aSource name , '  is already connected to ' , aDest name.
  315.             ^nil].
  316.     (aSource box arcedTo: aDest box)
  317.         ifTrue: 
  318.             [PopUpNotifier message: aSource name , '  is already connected to ' , aDest name.
  319.             ^nil].
  320.     source _ aSource.
  321.     destination _ aDest.
  322.     source addLink: self.
  323.     destination addLink: self.
  324.     self path: newPath! !
  325.  
  326. SDSLink subclass: #PipeLink
  327.     instanceVariableNames: ''
  328.     classVariableNames: ''
  329.     poolDictionaries: ''
  330.     category: 'SDS'!
  331. PipeLink comment:
  332. 'I am a link to pass flows.'!
  333.  
  334.  
  335. !PipeLink methodsFor: 'initialization'!
  336.  
  337. from: aSource to: aDest withPath: newPath 
  338.     "Initialize this FoibleLink linked from aSource to  
  339.     aDest, using the given newPath to make my form"
  340.     "move the acceptPipes checking in here instead of in PipeTool getPath for consistency in user interface"
  341.  
  342.     source isNil ifFalse: [self error: 'cannot re-initialize a ' , self class name].
  343.     (aDest box acceptsPipes)
  344.         ifFalse:[^nil].
  345.     (aDest box pipedTo: aSource box)
  346.         ifTrue: 
  347.             [PopUpNotifier message: 'Circular link: ' , aSource name , '  is already connected to ' , aDest name.
  348.             ^nil].
  349.     "this modification is made to make link already has both source and destination before a addlink: message is sent to a box"
  350.     source _ aSource.
  351.     destination _ aDest.
  352.     source addLink: self.
  353.     destination addLink: self.
  354.     self path: newPath! !
  355.  
  356. Object subclass: #TimeParameter
  357.     instanceVariableNames: 'startTime stopTime deltaTime '
  358.     classVariableNames: ''
  359.     poolDictionaries: ''
  360.     category: 'SDS'!
  361. TimeParameter comment:
  362. 'I define time parameter for simulation.
  363.     
  364. Instance variables:
  365.     startTime <aNumber>
  366.         initial time of simulation
  367.     stopTime <aNumber>
  368.         final time of simulation
  369.     deltaTime <aNumber>
  370.         delta time of simulation'!
  371.  
  372.  
  373. !TimeParameter methodsFor: 'user interface'!
  374.  
  375. edit
  376.     InspectorView open: (TimeParameterEditor inspect: self).! !
  377.  
  378. !TimeParameter methodsFor: 'testing'!
  379.  
  380. = aTimeParameter 
  381.     "equality test for time parameter"
  382.  
  383.     startTime ~= aTimeParameter startTime ifTrue: [^false].
  384.     stopTime ~= aTimeParameter stopTime ifTrue: [^false].
  385.     deltaTime ~= aTimeParameter deltaTime ifTrue: [^false]! !
  386.  
  387. !TimeParameter methodsFor: 'accessing'!
  388.  
  389. deltaTime
  390.     ^deltaTime!
  391.  
  392. deltaTime: aNumber
  393.     deltaTime _ aNumber!
  394.  
  395. startTime
  396.     ^startTime!
  397.  
  398. startTime: aNumber
  399.     startTime _ aNumber!
  400.  
  401. stopTime
  402.     ^stopTime!
  403.  
  404. stopTime: aNumber
  405.     stopTime _ aNumber! !
  406. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  407.  
  408. TimeParameter class
  409.     instanceVariableNames: ''!
  410.  
  411.  
  412. !TimeParameter class methodsFor: 'instance creation'!
  413.  
  414. newWithStartTime: aNumber1 stopTime: aNumber2 deltaTime: aNumber3 
  415.     | aTimeParameter |
  416.     aTimeParameter _ self new.
  417.     aTimeParameter startTime: aNumber1.
  418.     aTimeParameter stopTime: aNumber2.
  419.     aTimeParameter deltaTime: aNumber3.
  420.     ^aTimeParameter.! !
  421.  
  422. !TimeParameter class methodsFor: 'examples'!
  423.  
  424. example
  425.     
  426.     | aTimePar |
  427.     aTimePar _ TimeParameter newWithStartTime: 0 stopTime: 25 deltaTime: 0.5.
  428.     aTimePar edit.! !
  429.  
  430. BoxWithDirectLinks subclass: #SDSBox
  431.     instanceVariableNames: 'permanentForm entity minimumValue maximumValue '
  432.     classVariableNames: ''
  433.     poolDictionaries: ''
  434.     category: 'SDS'!
  435. SDSBox comment:
  436. 'I am the superclass of all types of boxes in SDS environment.
  437.     
  438. Instance variables:
  439.     
  440.     permanentForm <Form>
  441.         hold graphical form of my box
  442.     entity <Entity>
  443.         all information about my entity (my equation, my values for every time in 
  444.         simulation.
  445.     minimumValue <Number> 
  446.         minimum value used to display myself in graph (user defined) or
  447.         ''nil'' if default value is used.
  448.     maximumValue <Number>
  449.         same as above for maximum value.'!
  450.  
  451.  
  452. !SDSBox methodsFor: 'initialization'!
  453.  
  454. initializeAt: aPoint withName: aName 
  455.     "initialize the new FoibleBox at aPoint with form aForm"
  456.  
  457.     name isNil ifFalse: [^self error:'Cannot reinitialize a ',self class name].
  458.     name _ aName.
  459.     entity _ Entity withName: aName.
  460.     entity box: self.
  461.     self offset: aPoint.
  462.     links _ OrderedCollection new.!
  463.  
  464. initializeAt: aPoint withName: aName withForm: aForm superManager: aManager 
  465.     "initialize the new FoibleBox at aPoint with form aForm. Also put '?' in the box since it has no equation yet"
  466.  
  467.     name isNil ifFalse: [^self error: 'Cannot reinitialize a ' , self class name].
  468.     self initializeAt: aPoint withName: aName.
  469.     aName asString asDisplayText
  470.         displayOn: aForm
  471.         at: 3 @ 33
  472.         clippingBox: (2 @ 30 corner: 48 @ 48)
  473.         rule: Form over
  474.         mask: Form black.
  475.     '?' asDisplayText
  476.         displayOn: aForm
  477.         at: 22 @ 17
  478.         clippingBox: (2 @ 2 corner: 48 @ 48)
  479.         rule: Form over
  480.         mask: Form black.
  481.     self permanentForm: aForm.
  482.     owner _ aManager! !
  483.  
  484. !SDSBox methodsFor: 'updating'!
  485.  
  486. update
  487.     "update my appearance, put '?' if my equation is not yet defined"
  488.     
  489.     permanentForm _self class baseForm.
  490.     name asString asDisplayText
  491.         displayOn: permanentForm
  492.         at: 3 @ 33
  493.         clippingBox: (2 @ 30 corner: 48 @ 48)
  494.         rule: Form over
  495.         mask: Form black.
  496.     entity isCompiled ifFalse:['?' asDisplayText
  497.         displayOn: permanentForm
  498.         at: 22 @ 17
  499.         clippingBox: (2 @ 2 corner: 48 @ 48)
  500.         rule: Form over
  501.         mask: Form black].
  502.     forms _ OrderedCollection new.
  503.     forms add: permanentForm.
  504.  
  505.     owner changed: self boundingBox.! !
  506.  
  507. !SDSBox methodsFor: 'renaming'!
  508.  
  509. rename: newName
  510.     "rename myself with newName"
  511.  
  512.     name _ newName.
  513.     entity name: newName.
  514.     self update.! !
  515.  
  516. !SDSBox methodsFor: 'form access'!
  517.  
  518. baseForm
  519.     "Return a copy of the Form representing the receiver"  
  520.  
  521.     ^permanentForm deepCopy!
  522.  
  523. createForms
  524.     "This is the method that creates the form."
  525.  
  526.     | aForm |
  527.     aForm _ self baseForm.
  528.     aForm offset: 0@0.
  529.     forms add: aForm!
  530.  
  531. permanentForm: aForm
  532.     "set the permanent form of the receiver to be aForm"  
  533.  
  534.     permanentForm _ aForm! !
  535.  
  536. !SDSBox methodsFor: 'interface tests'!
  537.  
  538. acceptsArcs
  539.     "Return whether I give Arcs at the user interface"
  540.  
  541.     ^self acceptsArcs: nil!
  542.  
  543. acceptsArcs: aPoint 
  544.     "Return whether I give Arcs at the user interface"
  545.  
  546.     ^self defaultCase!
  547.  
  548. acceptsDataLinks: aPoint
  549.     "Return whether I accept Links at the user interface"
  550.  
  551.     ^self defaultCase.!
  552.  
  553. acceptsPipes
  554.     "Return whether I accept Pipes at the user interface"
  555.  
  556.     ^self acceptsPipes: nil.!
  557.  
  558. acceptsPipes: aPoint 
  559.     "Return whether I accept Pipes at the user interface"
  560.  
  561.     ^self defaultCase.!
  562.  
  563. defaultCase
  564.     "Return whether I give Arcs at the user interface, this is the default 
  565.     case for all interface tests"
  566.  
  567.     ^true!
  568.  
  569. givesArcs: aPoint 
  570.     "Return whether I give Arcs at the user interface"
  571.  
  572.     ^self defaultCase!
  573.  
  574. givesDataLinks: aPoint
  575.     "Return whether I give Links at the user interface"
  576.  
  577.     ^self defaultCase!
  578.  
  579. givesPipes: aPoint 
  580.     "Return whether I give Pipes at the user interface"
  581.  
  582.     ^self defaultCase! !
  583.  
  584. !SDSBox methodsFor: 'equation'!
  585.  
  586. editEquation
  587.     "edit my Entity equation"
  588.  
  589.     entity equationEditor recreateSymbolDictionary.
  590.     entity openView! !
  591.  
  592. !SDSBox methodsFor: 'accessing'!
  593.  
  594. arcedTo: aBox 
  595.     "Answer whether I am connected to aBox by an ArcLink"
  596.  
  597.     self links do: [:each | each class = ArcLink ifTrue: [(each linkedTo: aBox)
  598.                 ifTrue: [^true]]].
  599.     ^false!
  600.  
  601. entity
  602.     "Answer my entity"
  603.  
  604.     ^entity!
  605.  
  606. maximumValue
  607.     "return the maximum value of my entity"
  608.  
  609.     | max |
  610.     maximumValue = nil 
  611.         ifTrue: [entity orderedValues ~= nil
  612.             ifTrue: 
  613.                 [max _ entity orderedValues first.
  614.                 entity orderedValues 
  615.                     do: [:aValue | aValue > max 
  616.                             ifTrue: [max _ aValue]].
  617.                         ^max]
  618.             ifFalse: [^nil]].
  619.     ^maximumValue!
  620.  
  621. maximumValue: aValue
  622.     "set the maximum value"
  623.  
  624.     maximumValue _ aValue.!
  625.  
  626. maximumValueIsDefault
  627.     "my maximum value for graph is default if it is equal nil"
  628.  
  629.     ^maximumValue = nil!
  630.  
  631. minimumValue
  632.     "return the minimum value of my entity"
  633.  
  634.     | min |
  635.     minimumValue = nil ifTrue: [entity orderedValues ~= nil
  636.             ifTrue: 
  637.                 [min_ entity orderedValues first.
  638.                 entity orderedValues 
  639.                     do: [:aValue | aValue < min
  640.                             ifTrue: [min _ aValue]].
  641.                         ^min]
  642.             ifFalse: [^nil]].
  643.     ^minimumValue!
  644.  
  645. minimumValue: aValue
  646.     "set the minimum value"
  647.  
  648.     minimumValue _ aValue.!
  649.  
  650. minimumValueIsDefault
  651.     "my minimum value is default if it is equal nil"
  652.  
  653.     ^minimumValue = nil!
  654.  
  655. orderedValue
  656.     "return the orderedValue (values for each time slice) of my entity"
  657.     
  658.     ^entity orderedValues.!
  659.  
  660. pipedTo: aBox 
  661.     "Answer whether I am connected to aBox by a PipeLink"
  662.  
  663.     self links do: [:each | each class = PipeLink ifTrue: [(each linkedTo: aBox)
  664.                 ifTrue: [^true]]].
  665.     ^false!
  666.  
  667. resetState
  668.     "reset my entity's state, before initialization take place"
  669.  
  670.     entity resetState! !
  671. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  672.  
  673. SDSBox class
  674.     instanceVariableNames: ''!
  675.  
  676.  
  677. !SDSBox class methodsFor: 'form access'!
  678.  
  679. iconDirectory
  680.     "return the directory that contains the icons for the FlowKit"
  681.  
  682.     ^SDSDirectory iconDirectory! !
  683.  
  684. !SDSBox class methodsFor: 'instance creation'!
  685.  
  686. offset: aPoint withName: aString withForm: aForm
  687.     "create aType FoibleBox at aPoint with form aForm"
  688.  
  689.     | foibleBox |
  690.     foibleBox _ super new.
  691.     foibleBox initializeAt: aPoint withName: aString withForm: aForm.
  692.     ^foibleBox!
  693.  
  694. offset: aPoint withName: aString withForm: aForm superManager: aManager
  695.     "create aType FoibleBox at aPoint with form aForm"
  696.  
  697.     | foibleBox |
  698.     foibleBox _ super new.
  699.     foibleBox initializeAt: aPoint withName: aString withForm: aForm superManager: aManager.
  700.     ^foibleBox! !
  701.  
  702. !SDSBox class methodsFor: 'displaying'!
  703.  
  704. asCursor
  705.     "return an image of the receiver which can be used as a cursor"
  706.  
  707.     ^self baseForm deepCopy! !
  708.  
  709. SDSBox subclass: #FaucetBox
  710.     instanceVariableNames: 'inPipe outPipe '
  711.     classVariableNames: ''
  712.     poolDictionaries: ''
  713.     category: 'SDS'!
  714. FaucetBox comment:
  715. 'I am a controllable faucet. I only receive one input pipe and one output pipe. I can receive arcs (this is how my flow is defined/controlled) and give arcs (value of my flow can be used by other boxes).
  716.  
  717. Instance variables
  718.     inPipe    <PipeLink>
  719.         input pipe
  720.     outPipe <PipeLink>
  721.         output pipe
  722.     '!
  723.  
  724.  
  725. !FaucetBox methodsFor: 'accessing'!
  726.  
  727. inPipe
  728.     "Answer my input pipe link"
  729.  
  730.     ^inPipe!
  731.  
  732. inPipe: aPipeLink
  733.     "Set my input pipe"
  734.  
  735.     inPipe := aPipeLink.!
  736.  
  737. outPipe
  738.     "Answer my output pipe link"
  739.  
  740.     ^outPipe!
  741.  
  742. outPipe: aPipeLink
  743.     "Set my output pipe"
  744.  
  745.     outPipe := aPipeLink.! !
  746.  
  747. !FaucetBox methodsFor: 'adding'!
  748.  
  749. addLink: aLink 
  750.     "add aLink to myself"
  751.  
  752.     links add: aLink.
  753.     aLink class = PipeLink
  754.         ifTrue: [self = aLink source
  755.                 ifTrue: [outPipe := aLink]
  756.                 ifFalse: [inPipe := aLink]]
  757.         ifFalse: [self == aLink toBox ifTrue: [entity add: aLink source entity]].
  758.     self update! !
  759.  
  760. !FaucetBox methodsFor: 'interface tests'!
  761.  
  762. acceptsPipes: aPoint 
  763.     "Return whether I accept Pipes at the user interface"
  764.  
  765.     inPipe == nil
  766.         ifFalse: [PopUpNotifier message: 'Only one Pipe can be ended here'.
  767.                 ^false].
  768.     ^true.!
  769.  
  770. givesPipes: aPoint 
  771.     "Return whether I give Pipes at the user interface"
  772.  
  773.     outPipe == nil
  774.         ifFalse: [PopUpNotifier message: 'Only one Pipe can be originated here'.
  775.                  ^false].
  776.     ^true.! !
  777.  
  778. !FaucetBox methodsFor: 'removing'!
  779.  
  780. removeLink: aLink 
  781.     "remove a link from myself"
  782.  
  783.     links remove: aLink.
  784.     aLink class = PipeLink
  785.         ifTrue: 
  786.             [aLink = inPipe ifTrue: [inPipe _ nil].
  787.             aLink = outPipe ifTrue: [outPipe _ nil]]
  788.         ifFalse: [self = aLink toBox ifTrue: [entity delete: aLink source entity]].
  789.     self update.! !
  790.  
  791. SDSBox subclass: #CombinerBox
  792.     instanceVariableNames: ''
  793.     classVariableNames: ''
  794.     poolDictionaries: ''
  795.     category: 'SDS'!
  796. CombinerBox comment:
  797. 'I combine values and the result can be used by other box (except stock box).
  798. I only give and accept arcs (I do not deal with flow).'!
  799.  
  800.  
  801. !CombinerBox methodsFor: 'interface tests'!
  802.  
  803. acceptsPipes: aPoint 
  804.     "Return whether I accept Pipes at the user interface"
  805.  
  806.     PopUpNotifier message: 'Pipe cannot be ended here'.
  807.      ^false!
  808.  
  809. givesPipes: aPoint 
  810.     "Return whether I give Pipes at the user interface"
  811.  
  812.     PopUpNotifier message: 'Pipe cannot be originated from here'.
  813.     ^false! !
  814.  
  815. !CombinerBox methodsFor: 'removing'!
  816.  
  817. removeLink: aLink 
  818.     "remove a link from myself"
  819.  
  820.     links remove: aLink.
  821.     self = aLink toBox ifTrue: [entity delete: aLink source entity].
  822.     self update.! !
  823.  
  824. !CombinerBox methodsFor: 'adding'!
  825.  
  826. addLink: aLink 
  827.     links add: aLink.
  828.     self = aLink toBox ifTrue: ["my entity only receives ArcLink"
  829.         entity add: aLink source entity].
  830.     self update.! !
  831.  
  832. SDSBox subclass: #StockBox
  833.     instanceVariableNames: ''
  834.     classVariableNames: ''
  835.     poolDictionaries: ''
  836.     category: 'SDS'!
  837. StockBox comment:
  838. 'I am a kind of box which used to accumulate values (or you can call me a ''container''). I can give and accept pipes (that how my flow is defined).
  839. I can give arcs but cannot accept arcs (my value can be used by other boxes but I cannot receive any values but flows).
  840. My entity is a StockEntity (a subclass of Entity), so only my initial value is need to be defined (my equation is implicitly defined).
  841. '!
  842.  
  843.  
  844. !StockBox methodsFor: 'interface tests'!
  845.  
  846. acceptsArcs: aPoint 
  847.     "Return whether I give Arcs at the user interface"
  848.  
  849.     PopUpNotifier message: 'Arc cannot be ended here'.
  850.     ^false! !
  851.  
  852. !StockBox methodsFor: 'initialization'!
  853.  
  854. initializeAt: aPoint withName: aName 
  855.     "initialize the new StockBox at aPoint with name aName"
  856.  
  857.     name isNil ifFalse: [^self error: 'Cannot reinitialize a ' , self class name].
  858.     name _ aName.
  859.     entity _ StockEntity withName: aName. 
  860.     entity box: self.
  861.     self offset: aPoint.
  862.     links _ OrderedCollection new! !
  863.  
  864. !StockBox methodsFor: 'adding'!
  865.  
  866. addLink: aLink 
  867.     "My entity only care about inPipe and outPipe"
  868.  
  869.     links add: aLink.
  870.     aLink class = PipeLink ifTrue: [self = aLink box
  871.             ifTrue: [entity addOutput: aLink toBox entity]
  872.             ifFalse: [entity addInput: aLink source entity]].
  873.     self update.! !
  874.  
  875. !StockBox methodsFor: 'removing'!
  876.  
  877. removeLink: aLink 
  878.     "My entity only care about inPipe and outPipe"
  879.  
  880.     links remove: aLink.
  881.     aLink class = PipeLink ifTrue: [self = aLink box
  882.             ifTrue: [entity deleteOutput: aLink toBox entity]
  883.             ifFalse: [entity deleteInput: aLink source entity]].
  884.     self update.! !
  885.  
  886. !StockBox methodsFor: 'menu messages'!
  887.  
  888. editEquation
  889.     "my initial value can be defined from any other boxes in the 
  890.     environment, hence my symbol dictionary holds every boxes in 
  891.     current environment"
  892.  
  893.     entity createSymbolDict: owner boxes.
  894.     entity openView! !
  895.  
  896. Tool subclass: #SDSTool
  897.     instanceVariableNames: ''
  898.     classVariableNames: ''
  899.     poolDictionaries: ''
  900.     category: 'SDS'!
  901. SDSTool comment:
  902. 'I am the superclass of all Stella tools. I receive the message from SDSController.
  903. See Tool in Foible for more details.'!
  904.  
  905.  
  906. !SDSTool methodsFor: 'menu setup'!
  907.  
  908. installMenu
  909.     "I will not respond to any yellowButton, an SDSController will take 
  910.     care of this"
  911.  
  912.     controller yellowButtonMenu: nil yellowButtonMessages: nil! !
  913.  
  914. !SDSTool methodsFor: 'menu messages'!
  915.  
  916. add: aClass 
  917.     "Get a point in the viewport and add a Foible of the class  aClass there"
  918.  
  919.     | aPoint aThing currentModel aCursor |
  920.     currentModel _ model.
  921.     aCursor _ aClass asCursor.
  922.     aPoint _ self getThingPoint: aCursor.
  923.     aPoint isNil ifTrue: [^nil].
  924.     currentModel _ self getManager: aPoint.
  925.     currentModel isNil ifTrue: [^nil].
  926.     aThing _ currentModel addBox: [:name | aClass
  927.                     offset: aPoint
  928.                     withName: name
  929.                     withForm: aCursor
  930.                     superManager: currentModel]. 
  931.     model changed: aThing!
  932.  
  933. add: aClass withForm: aForm 
  934.     "Get a point in the viewport and add a Foible of the class     
  935.            aClass there. Then reset the permanent form"
  936.  
  937.     | aPoint aThing currentModel aCursor |
  938.     currentModel _ model.
  939.     aCursor _ aForm.
  940.     aPoint _ self getThingPoint: aCursor.
  941.     aPoint isNil ifTrue: [^nil].
  942.     currentModel _ self getManager: aPoint.
  943.     currentModel isNil ifTrue: [^nil].
  944.     aThing _ currentModel addBox: [:name | aClass
  945.                     offset: aPoint
  946.                     withName: name
  947.                     withForm: aCursor]. 
  948.     currentModel lastBox permanentForm: aClass asCursor.
  949.     model changed: aThing!
  950.  
  951. addToGraph: aBox 
  952.     "add aBox to plotBoxesOC of my manager"
  953.  
  954.     | anOC |
  955.     anOC _ model plotBoxesOC.
  956.     anOC do: [:eachBox | "return myself if aBox is already in plotBoxesOC"
  957.         eachBox = aBox ifTrue: [^self]].    
  958.     anOC addLast: aBox!
  959.  
  960. deleteBox: aBox 
  961.     "delete aBox"
  962.  
  963.     | aRectangle |
  964.     (BinaryChoice message: ('Really delete\' , aBox name , '?') withCRs)
  965.         ifFalse: [^nil].
  966.     aRectangle _ aBox owner remove: aBox.
  967.     model changed: aRectangle!
  968.  
  969. deleteFromGraph: aBox 
  970.     "remove aBox from plotBoxesOC of my manager"
  971.  
  972.     model plotBoxesOC remove: aBox ifAbsent: [^nil].!
  973.  
  974. deleteLink: aLink
  975.     "delete aLink"
  976.     
  977.     aLink delete.!
  978.  
  979. editEquation: aBox 
  980.     "edit equation of aBox"
  981.  
  982.     aBox editEquation.!
  983.  
  984. getManager: aPoint 
  985.     "return the manager of the box at aPoint"
  986.  
  987.     | aBox |
  988.     aBox _ model find: aPoint.
  989.     aBox isNil
  990.         ifTrue: [^model]
  991.         ifFalse: [^aBox manager]!
  992.  
  993. moveBox: aBox 
  994.     "move aBox"
  995.  
  996.     | aRectangle newPoint |
  997.     Sensor cursorPoint: (view displayTransform: aBox offset).
  998.     newPoint _ self getThingPoint: aBox ghostForm.
  999.     newPoint isNil ifTrue: [^nil].
  1000.     aRectangle _ model moveBox: aBox byBlock: [:box | box offset: newPoint].
  1001.     aRectangle notNil ifTrue: [model changed: aRectangle].
  1002.     model cursor show!
  1003.  
  1004. renameBox: aBox 
  1005.     "rename aBox"
  1006.  
  1007.     |  newName aSDSView |
  1008.     newName _ (FillInTheBlank request: 'Name:' initialAnswer: aBox name asString) asSymbol.
  1009.     aBox rename: newName.
  1010.     "hack to show tools pallete"
  1011.     "aSDSView _ model program dependents first.
  1012.     aSDSView controller startUp."!
  1013.  
  1014. showTable: aBox 
  1015.     "show my simulation result in table format"
  1016.  
  1017.     | timeParameter aTable |
  1018.     model simulated = false | (aBox entity orderedValues = nil) ifTrue: [^PopUpNotifier message: 'no result yet'].
  1019.     timeParameter _ model timeParameter.
  1020.     aTable _ Table
  1021.                 withStartIndex: timeParameter startTime
  1022.                 stopIndex: timeParameter stopTime
  1023.                 delta: timeParameter deltaTime
  1024.                 orderedValues: aBox entity orderedValues
  1025.                 indexTitle: #time
  1026.                 valueTitle: aBox name.
  1027.     aTable buildTable.
  1028.     TableView openOn: aTable!
  1029.  
  1030. updateBox: aBox 
  1031.     "update aBox, show current status (whether need to show '?' or not"
  1032.  
  1033.     aBox update! !
  1034. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1035.  
  1036. SDSTool class
  1037.     instanceVariableNames: ''!
  1038.  
  1039.  
  1040. !SDSTool class methodsFor: 'form access'!
  1041.  
  1042. iconDirectory
  1043.     "return the directory that contains the icons for FlowKit"
  1044.  
  1045.     ^SDSDirectory iconDirectory! !
  1046.  
  1047. SDSTool subclass: #HandTool
  1048.     instanceVariableNames: ''
  1049.     classVariableNames: 'SkullCursor '
  1050.     poolDictionaries: ''
  1051.     category: 'SDS'!
  1052. HandTool comment:
  1053. 'Tool for moving things around.'!
  1054.  
  1055.  
  1056. !HandTool methodsFor: 'menu messages'!
  1057.  
  1058. delete
  1059.     "Find an object and remove it from list, return nil if no find"
  1060.  
  1061.     | aPoint aThing aRectangle |
  1062.     aPoint _ self getPoint: self class skullCursor.
  1063.     aPoint isNil ifTrue: [^nil].
  1064.     "User aborted"
  1065.     aThing _ model find: aPoint suchThat: [:it | it canBeDeleted].
  1066.     aThing isNil ifTrue: [^nil].
  1067.     "No such object"
  1068.     Sensor waitNoButton.
  1069.     (BinaryChoice message: 'Really delete
  1070. ' , aThing name , '?')
  1071.         ifFalse: [^nil].
  1072.     self halt.
  1073.     aRectangle _ aThing owner remove: aThing.
  1074.     model changed: aRectangle.!
  1075.  
  1076. move
  1077.     "Find an object and move it"
  1078.  
  1079.     | oldThing newPoint aRectangle |
  1080.     newPoint _ self getPoint: self class cursor.
  1081.     newPoint isNil ifTrue: [^nil].
  1082.     oldThing _ model find: newPoint suchThat: [:it | "User aborted"
  1083.                 it canMoveIndependently].
  1084.     oldThing isNil ifTrue: [^nil].
  1085.     Sensor waitNoButton.
  1086.     (oldThing isKindOf: self defaultLinkClass)
  1087.         ifTrue: [aRectangle _ self moveLine: oldThing point: newPoint].
  1088.     (oldThing isKindOf: FoibleBox)
  1089.         ifTrue: 
  1090.             [Sensor cursorPoint: (view displayTransform: oldThing offset).
  1091.             newPoint _ self getThingPoint: oldThing ghostForm.
  1092.             newPoint isNil ifTrue: [^nil].
  1093.             aRectangle _ model moveBox: oldThing byBlock: [:box | box offset: newPoint]].
  1094.     aRectangle notNil ifTrue: [model changed: aRectangle].
  1095.     model cursor show! !
  1096.  
  1097. !HandTool methodsFor: 'menu setup'!
  1098.  
  1099. installMenu
  1100.     "Install our menu"
  1101.  
  1102.     controller yellowButtonMenu:
  1103.                  (PopUpMenu labels: 'rename\delete' withCRs)
  1104.     yellowButtonMessages: #(#rename #delete).!
  1105.  
  1106. redButtonActivity
  1107.     self move! !
  1108.  
  1109. !HandTool methodsFor: 'private'!
  1110.  
  1111. getPoint: aCursor
  1112.  
  1113.     "Get a point in the viewport and return its value, nil if left the viewport"
  1114.  
  1115.     | aPoint |
  1116.     aCursor show.
  1117.     [ Sensor noButtonPressed & controller isControlActive ]
  1118.             whileTrue: [aPoint _ Sensor cursorPoint].
  1119.  
  1120.     model cursor show.
  1121.     controller isControlActive ifFalse: [^nil].
  1122.     ^(view inverseDisplayTransform: (Sensor waitButton)) rounded! !
  1123. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1124.  
  1125. HandTool class
  1126.     instanceVariableNames: ''!
  1127.  
  1128.  
  1129. !HandTool class methodsFor: 'accessing'!
  1130.  
  1131. cursorOffset
  1132.     "Return the offset of my cursor"
  1133.  
  1134.     ^ 0 @ -6!
  1135.  
  1136. skullCursor
  1137.  
  1138.     SkullCursor isNil ifTrue: [SkullCursor _ (self getCursor: 'HandTool.cur')
  1139.                     offset: -7 @ -9].
  1140.     ^SkullCursor! !
  1141.  
  1142. SDSTool subclass: #StockTool
  1143.     instanceVariableNames: ''
  1144.     classVariableNames: ''
  1145.     poolDictionaries: ''
  1146.     category: 'SDS'!
  1147. StockTool comment:
  1148. 'I am tool for stock box'!
  1149.  
  1150.  
  1151. !StockTool methodsFor: 'menu messages'!
  1152.  
  1153. redButtonActivity
  1154.     "add a foible of type Stock"
  1155.  
  1156.     self add: StockBox! !
  1157.  
  1158. SDSTool subclass: #CombinerTool
  1159.     instanceVariableNames: ''
  1160.     classVariableNames: ''
  1161.     poolDictionaries: ''
  1162.     category: 'SDS'!
  1163. CombinerTool comment:
  1164. 'I am the tool for Combiner box
  1165. '!
  1166.  
  1167.  
  1168. !CombinerTool methodsFor: 'menu messages'!
  1169.  
  1170. redButtonActivity
  1171.  
  1172.     self add: CombinerBox.! !
  1173.  
  1174. SDSTool subclass: #FaucetTool
  1175.     instanceVariableNames: ''
  1176.     classVariableNames: ''
  1177.     poolDictionaries: ''
  1178.     category: 'SDS'!
  1179. FaucetTool comment:
  1180. 'I am the tool for Faucet box'!
  1181.  
  1182.  
  1183. !FaucetTool methodsFor: 'menu messages'!
  1184.  
  1185. redButtonActivity
  1186.  
  1187.     self add: FaucetBox.! !
  1188. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1189.  
  1190. FaucetTool class
  1191.     instanceVariableNames: ''!
  1192.  
  1193.  
  1194. !FaucetTool class methodsFor: 'accessing'!
  1195.  
  1196. cursorOffset
  1197.     " return the offset of my cursor "
  1198.  
  1199.     ^ -8 @ -9! !
  1200.  
  1201. SDSTool subclass: #PipeTool
  1202.     instanceVariableNames: ''
  1203.     classVariableNames: ''
  1204.     poolDictionaries: ''
  1205.     category: 'SDS'!
  1206. PipeTool comment:
  1207. 'Tool for PipeLink'!
  1208.  
  1209.  
  1210. !PipeTool methodsFor: 'menu messages'!
  1211.  
  1212. add
  1213.     "link this type of link"
  1214.  
  1215.     | fromThing toThing link aProtoLink lines |
  1216.     aProtoLink _ self getPath.
  1217.     aProtoLink isNil ifTrue: [^nil].
  1218.     fromThing _ aProtoLink origin.
  1219.     toThing _ aProtoLink destination.
  1220.     lines _ aProtoLink lines.
  1221.     link _ fromThing box owner
  1222.                 addLink: PipeLink
  1223.                 from: fromThing
  1224.                 to: toThing
  1225.                 withPath: lines.
  1226.     link isNil ifTrue: [^nil].
  1227.     model changed: link!
  1228.  
  1229. getPath
  1230.     "Allow the user to draw the path between the two boxes   
  1231.     (with appropriate conditions) and return the path"
  1232.  
  1233.     ^self
  1234.         pathFrom: [:it :point | it givesPipes: point]
  1235.         to: [:it :point | it acceptsDataLinks: point]
  1236.         width: self defaultLinkClass width
  1237.         both: [:a :b | (a box ~= b box) & (a class ~= b class)]
  1238.         " to prevent pipes from faucet to faucet or from stock to stock"!
  1239.  
  1240. redButtonActivity
  1241.     "red button activity for PipeLinkTool"
  1242.  
  1243.     self add! !
  1244.  
  1245. SDSTool subclass: #ArcTool
  1246.     instanceVariableNames: ''
  1247.     classVariableNames: ''
  1248.     poolDictionaries: ''
  1249.     category: 'SDS'!
  1250. ArcTool comment:
  1251. 'I am the tool for ArcLink'!
  1252.  
  1253.  
  1254. !ArcTool methodsFor: 'menu messages'!
  1255.  
  1256. add 
  1257.     "link this type of link"
  1258.  
  1259.     | fromThing toThing link  aProtoLink lines |
  1260.     aProtoLink _ self getPath.
  1261.     aProtoLink isNil ifTrue: [^nil].
  1262.     fromThing _ aProtoLink origin.
  1263.     toThing _ aProtoLink destination.
  1264.     lines _ aProtoLink lines.
  1265.     link _fromThing box owner 
  1266.                 addLink: ArcLink
  1267.                 from: fromThing
  1268.                 to: toThing
  1269.                 withPath: lines.
  1270.     link isNil ifTrue: [^nil].
  1271.     model changed: link.!
  1272.  
  1273. getPath
  1274.     "Allow the user to draw the path between the two boxes 
  1275.     (with appropriate conditions) and return the path."
  1276.     "The condition is that the source should be able to give arcs and the 
  1277.     destination should be able to receive Arcs. The destination condition 
  1278.     will be tested in ArcLink from:to:withPat: along with circularity test."
  1279.  
  1280.     ^self
  1281.         pathFrom: [:it :point | it givesArcs: point]
  1282.         to: [:it :point | it acceptsDataLinks: point]
  1283.         width: self defaultLinkClass width
  1284.         both: [:a :b | a box ~= b box]!
  1285.  
  1286. redButtonActivity
  1287.     "red button activity for ArcLinkTool"
  1288.  
  1289.     self add! !
  1290.  
  1291. !ArcTool methodsFor: 'menu setup'!
  1292.  
  1293. installMenu 
  1294.     "install our menu"
  1295.  
  1296.     controller yellowButtonMenu: nil
  1297.         yellowButtonMessages: nil! !
  1298.  
  1299. ToolBenchView subclass: #SDSView
  1300.     instanceVariableNames: ''
  1301.     classVariableNames: ''
  1302.     poolDictionaries: ''
  1303.     category: 'SDS'!
  1304. SDSView comment:
  1305. 'I am the top level view of SDS environment. Nothing new defined here (see ToolBenchView in Foible for further details).'!
  1306.  
  1307.  
  1308. !SDSView methodsFor: 'initialize'!
  1309.  
  1310. initializeWithModel: aStellaProgram 
  1311.     "initialize my model to be aStellaProgram and create a new canvas"
  1312.  
  1313.     | aCanvasView |
  1314.     self model: aStellaProgram.
  1315.     aCanvasView _ CanvasView new.
  1316.     aCanvasView model: aStellaProgram firstManager.
  1317.     self
  1318.         addSubView: aCanvasView
  1319.         in: (0 @ 0 extent: 1 @ 1)
  1320.         borderWidth: 1.
  1321.     canvas _ OrderedCollection with: aCanvasView! !
  1322.  
  1323. !SDSView methodsFor: 'subview access'!
  1324.  
  1325. canvas
  1326.     ^canvas! !
  1327.  
  1328. !SDSView methodsFor: 'private'!
  1329.  
  1330. installCanvasTools
  1331.     "tell my canvases what their Tools are"
  1332.  
  1333.     (self canvas at: 1) addTools: (OrderedCollection new
  1334.         add: HandTool new;
  1335.         add: StockTool new;
  1336.         add: CombinerTool new;
  1337.         add: FaucetTool new;
  1338.         add: ArcTool new;
  1339.         add: PipeTool new;
  1340.     yourself).!
  1341.  
  1342. tools
  1343.     "return an OrderedCollection of the icons for the palette"
  1344.  
  1345.     ^(OrderedCollection new
  1346.         add: HandTool icon;
  1347.         add: StockTool icon;
  1348.         add: CombinerTool icon;
  1349.         add: FaucetTool icon;
  1350.         add: ArcTool icon;
  1351.         add: PipeTool icon;
  1352.     yourself)! !
  1353. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1354.  
  1355. SDSView class
  1356.     instanceVariableNames: ''!
  1357.  
  1358.  
  1359. !SDSView class methodsFor: 'instance creation'!
  1360.  
  1361. open
  1362.     "Create a new StellaManager and open a StellaView on it"
  1363.     "SDSView open"
  1364.  
  1365.     self openOn: (SDSProgram with: SDSManager new).!
  1366.  
  1367. openOn: aFoibleProgram 
  1368.     "Create and install views of aFoibleProgram and their menu."
  1369.  
  1370.     | toolBenchView topView |
  1371.     SDSController initialize.
  1372.     EquationEditor initialize.
  1373.     TimeParameterEditor initialize.
  1374.     EquationParser initializeFunctionDict: EquationEditor functionDictionary.
  1375.     toolBenchView _ self model: aFoibleProgram.
  1376.     toolBenchView canvasController: [SDSController new].
  1377.     toolBenchView insideColor: Form gray.
  1378.     toolBenchView installCanvasTools.
  1379.     topView _ FoibleView new
  1380.         model: aFoibleProgram;
  1381.         label: aFoibleProgram name;
  1382.         addSubView: toolBenchView in: (0@0 extent: 1@1) borderWidth: 0.
  1383.     topView minimumSize: 200@400.
  1384.     topView controller open!
  1385.  
  1386. openProgram
  1387.     "Open an existing StellaView program; saved as a binary"
  1388.     "StellaView openProgram." 
  1389.  
  1390.     ^super openProgram!
  1391.  
  1392. openProgram: aName 
  1393.     "Open an existing StellaView program saved as a binary"
  1394.     "StellaView openProgram: <aName>. "
  1395.  
  1396.     ^super openProgram: aName! !
  1397.  
  1398. Object subclass: #SDSDirectory
  1399.     instanceVariableNames: ''
  1400.     classVariableNames: ''
  1401.     poolDictionaries: ''
  1402.     category: 'SDS'!
  1403. SDSDirectory comment:
  1404. 'I define icon directory of SDS.'!
  1405.  
  1406. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1407.  
  1408. SDSDirectory class
  1409.     instanceVariableNames: ''!
  1410.  
  1411.  
  1412. !SDSDirectory class methodsFor: 'form access'!
  1413.  
  1414. iconDirectory
  1415.     "return the directory that contains the icons for the SDS"
  1416.  
  1417.     ^'/home/sutanto/smalltalk/SDS/icons'! !
  1418.  
  1419. FoibleManager subclass: #SDSManager
  1420.     instanceVariableNames: 'timeParameter plotBoxesOC simulated modeCalculation '
  1421.     classVariableNames: ''
  1422.     poolDictionaries: ''
  1423.     category: 'SDS'!
  1424. SDSManager comment:
  1425. 'I manage and control simulation processes.
  1426.     
  1427. Instance Variables:
  1428.     
  1429.     timeParameter <TimeParameter>
  1430.         defines the simulation time
  1431.     plotBoxesOC <OrderedCollection>
  1432.         holds boxes to be displayed in a graph
  1433.     simulated <Boolean>
  1434.         whether simulation has already taken place
  1435.     modeCalculation <Symbol>
  1436.         mode of calculation used in the simulation
  1437.         there are two possible values for this:
  1438.             #default  for Euler approximation
  1439.             #rungeKutta2 for second order Runge-Kutta (this part is still bogus
  1440.             though).'!
  1441.  
  1442.  
  1443. !SDSManager methodsFor: 'menu messages'!
  1444.  
  1445. graphParameters
  1446.     "List parameters for all graph variables (plotted box values) and provide interactive editing for minimum/maximum of graph variables"
  1447.  
  1448.     (plotBoxesOC = nil)  | (plotBoxesOC size = 0)
  1449.         ifTrue: [PopUpNotifier message: 'No graph parameter']
  1450.         ifFalse: [GraphList withBoxes: plotBoxesOC ].!
  1451.  
  1452. listEquations
  1453.     "list all equations of current simulation"
  1454.  
  1455.     EquationListMenu withBoxes: boxes.!
  1456.  
  1457. runSimulation
  1458.     "run the simulation"
  1459.  
  1460.     | maxIndex |
  1461.     TimeTree
  1462.         initTime: timeParameter startTime
  1463.         finalTime: timeParameter stopTime
  1464.         delta: timeParameter deltaTime.
  1465.     DtTree delta: timeParameter deltaTime.
  1466.     self update.
  1467.     boxes do: 
  1468.         [:box | 
  1469.         box resetState.
  1470.         box entity isCompiled
  1471.             ifFalse: 
  1472.                 [PopUpNotifier message: box name asString , ' is not yet compiled'.
  1473.                 ^nil].
  1474.         box entity class = StockEntity ifTrue: [box entity parseText]].
  1475.     maxIndex _ (timeParameter stopTime - timeParameter startTime / timeParameter deltaTime) rounded + 1.
  1476.     Cursor wait showWhile: [1 to: maxIndex do: [:index | boxes do: [:box | box entity valueAt: index modeCalc: self modeCalculation ]]].
  1477.     simulated _ true!
  1478.  
  1479. setCalculationMode
  1480.     "set my current calculation mode"
  1481.  
  1482.     | result |
  1483.     result _ (PopUpMenu labels: 'Euler\2nd Runge-Kutta' withCRs) startUp.
  1484.     result = 1
  1485.         ifTrue: [modeCalculation _ #default]
  1486.         ifFalse: [modeCalculation _ #rungeKutta2]!
  1487.  
  1488. showGraph
  1489.     "plot my graph in other window"
  1490.  
  1491.     | aGraph totalBoxes |
  1492.     simulated = nil ifTrue: [^PopUpNotifier message: 'Run simulation first'].
  1493.     plotBoxesOC = nil | (plotBoxesOC size = 0) ifTrue: [^PopUpNotifier message: 'No plotted variable'].
  1494.     Cursor wait
  1495.         showWhile: 
  1496.             [aGraph _ Graph new.
  1497.             aGraph initialize.
  1498.             aGraph label: 'Graph'.
  1499.             aGraph
  1500.                 timeVariableWithMinimum: timeParameter startTime
  1501.                 maximum: timeParameter stopTime
  1502.                 delta: timeParameter deltaTime.
  1503.             totalBoxes _ 0.
  1504.             plotBoxesOC do: [:currentBox | totalBoxes < 4 ifTrue: [currentBox orderedValue = nil
  1505.                         ifFalse: 
  1506.                             [aGraph
  1507.                                 addPlotVariableWithName: currentBox name asString
  1508.                                 minimum: currentBox minimumValue
  1509.                                 maximum: currentBox maximumValue
  1510.                                 data: currentBox orderedValue
  1511.                                 mask: (Graph mask: totalBoxes).
  1512.                             totalBoxes _ totalBoxes + 1]]].
  1513.             aGraph display].
  1514.     GraphView openOn: aGraph!
  1515.  
  1516. timeDefinition
  1517.     "define my time parameter"
  1518.     
  1519.     simulated _ false.    
  1520.     timeParameter edit.!
  1521.  
  1522. update
  1523.     "update all my boxes according to their current status (isCompiled or not)"
  1524.  
  1525.     boxes do: [:box | box update].! !
  1526.  
  1527. !SDSManager methodsFor: 'initialize'!
  1528.  
  1529. initialize
  1530.     "initialize mysefl and set my time parameter's defaults"
  1531.  
  1532.     super initialize.
  1533.     timeParameter _ TimeParameter newWithStartTime: 0 stopTime: 25 deltaTime: 0.5.! !
  1534.  
  1535. !SDSManager methodsFor: 'accessing'!
  1536.  
  1537. boxes
  1538.     "Answer my boxes"
  1539.     
  1540.     ^boxes!
  1541.  
  1542. modeCalculation
  1543.     "Answer my calculation mode"
  1544.  
  1545.     modeCalculation = nil ifTrue: [modeCalculation _ #default].
  1546.     ^modeCalculation!
  1547.  
  1548. plotBoxesOC
  1549.     "Answer ordered collection of my boxes which will be displayed in 
  1550.     graph"
  1551.  
  1552.     plotBoxesOC = nil ifTrue: [plotBoxesOC _ OrderedCollection new].
  1553.     ^plotBoxesOC!
  1554.  
  1555. simulated
  1556.     "Answer whether my simulation has already taken place"
  1557.  
  1558.     ^simulated!
  1559.  
  1560. timeParameter
  1561.     "Answer my current time parameter for simulation"
  1562.  
  1563.     ^timeParameter! !
  1564.  
  1565. !SDSManager methodsFor: 'adding'!
  1566.  
  1567. addBox: boxBlock
  1568.     "add a new FoibleBox created with boxBlock with the latest name"
  1569.  
  1570.     | foibleBox name stream |
  1571.     name _ 'Box','#############'.
  1572.     stream _ WriteStream on: name from: 4 to: (name size).
  1573.     nameNum printOn: stream.
  1574.     name _ name copyUpTo: $#.
  1575.     nameNum _ nameNum + 1. 
  1576.     foibleBox _ boxBlock value: name asSymbol. 
  1577.     boxes add: foibleBox.
  1578.     ^foibleBox boundingBox! !
  1579.  
  1580. Inspector subclass: #TimeParameterEditor
  1581.     instanceVariableNames: ''
  1582.     classVariableNames: 'FieldList '
  1583.     poolDictionaries: ''
  1584.     category: 'SDS'!
  1585. TimeParameterEditor comment:
  1586. 'I am the model for editing time parameter.
  1587.     
  1588. Class variable:
  1589.     FieldList        <Array>
  1590.         content the field list for time parameter (startTime stopTime and deltaTime)
  1591.  
  1592. '!
  1593.  
  1594.  
  1595. !TimeParameterEditor methodsFor: 'field list'!
  1596.  
  1597. fieldList
  1598.     ^self class fieldList!
  1599.  
  1600. fieldMenu
  1601.     "Answer an ActionMenu of operations on the variables that is to be displayed 
  1602.     when the operate menu button is pressed."
  1603.  
  1604.     ^nil! !
  1605.  
  1606. !TimeParameterEditor methodsFor: 'initialize-release'!
  1607.  
  1608. edit: aTimeParameter
  1609.     "Set aTimeParameterto be the object inspected by the receiver."
  1610.  
  1611.     self inspect: aTimeParameter! !
  1612. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1613.  
  1614. TimeParameterEditor class
  1615.     instanceVariableNames: ''!
  1616.  
  1617.  
  1618. !TimeParameterEditor class methodsFor: 'field list'!
  1619.  
  1620. fieldList
  1621.     ^FieldList! !
  1622.  
  1623. !TimeParameterEditor class methodsFor: 'class initialization'!
  1624.  
  1625. initialize
  1626.     FieldList _ TimeParameter allInstVarNames.! !
  1627.  
  1628. !TimeParameterEditor class methodsFor: 'instance creation '!
  1629.  
  1630. edit: aTimeParameter 
  1631.     "Answer an instance of me to provide an inspector for aTimeParameter"
  1632.     ^self new inspect: aTimeParameter.! !
  1633.  
  1634. TimeParameterEditor initialize!
  1635.